/**
 *Copyright 2013 by dragon.
 *
 *File name: Main.java
 *Author:      dragon
 *Email:       fufulove2012@gmail.com
 *Blog:        http://blog.csdn.net/xidomlove
 *Version:     1.0.0
 *Date:        2013-10-2 下午4:49:35
 *Description: 
 */
package com.dragon.jsnative;

import java.applet.Applet;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;

import netscape.javascript.JSObject;

/**
 * @author dragon8
 * 
 */
public class Main extends Applet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1611938488363007519L;

	/**
	 * 
	 */
	public Main() {
		// TODO Auto-generated constructor stub
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("JsNative version 1.0");
	}

	public String str() {
		return "你好 JsNative version 1.0";
	}

	public Class<?> getJavaClass(final String className) {
		return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {

			@Override
			public Class<?> run() {
				// TODO Auto-generated method stub
				try {
					return Class.forName(className);
				} catch (ClassNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				return null;
			}

		});
	}

	public String getJavaString(String obj) {
		return obj;
	}

	public Byte getJavaByte(Byte b) {
		return b;
	}

	public Boolean getJavaBoolean(Boolean b) {
		return b;
	}

	public Short getJavaShort(Short s) {
		return s;
	}

	public Character getJavaCharacter(Character b) {
		return b;
	}

	public Integer getJavaInteger(Integer b) {
		return b;
	}

	public Long getJavaLong(Long b) {
		return b;
	}

	public Float getJavaFloat(Float b) {
		return b;
	}

	public Double getJavaDouble(Double b) {
		return b;
	}

	public Object castObject(Object object, Class<?> cls) {
		return cls.cast(object);
	}

	public Thread createThread(final JSObject jsObject) {
		Thread thread = new Thread(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				jsObject.call("run", null);
			}
		});
		thread.start();
		return thread;
	}

	public Object invokeMethod(final Method method, final Object object,
			final Object[] args) {
		return AccessController.doPrivileged(new PrivilegedAction<Object>() {

			@Override
			public Object run() {
				// TODO Auto-generated method stub
				try {
					return method.invoke(object, args);
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				return null;
			}

		});
	}

	public Object newInstance(final Class<?> cls, final Class<?>[] argsCls,
			final Object[] args) {
		return AccessController.doPrivileged(new PrivilegedAction<Object>() {

			@Override
			public Object run() {
				// TODO Auto-generated method stub
				try {
					for (int i = 0; i < args.length; i++) {
						if (argsCls[i] == String.class) {
							args[i] = String.valueOf(args[i]);
						}
					}
					return cls.getConstructor(argsCls).newInstance(args);
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (InstantiationException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (NoSuchMethodException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (SecurityException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				return null;
			}

		});
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.applet.Applet#start()
	 */
	@Override
	public void start() {
		// TODO Auto-generated method stub
		super.start();

		// 重定向输出到浏览器控制台
		System.setOut(new PrintStream(new OutputStream() {
			JSObject jconsole = null;

			ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

			@Override
			public void write(int arg0) throws IOException {
				// TODO Auto-generated method stub
				arg0 = arg0 & 0xff;
				try {
					if (jconsole == null) {
						jconsole = (JSObject) JSObject.getWindow(Main.this)
								.getMember("console");
					}
					if (arg0 == 10 || arg0 == 13) {
						outputStream.write(0);
						jconsole.call("log",
								new Object[] { outputStream.toString() });
						outputStream.reset();
					} else {
						outputStream.write(arg0);
					}
				} catch (Exception e) {
					// TODO: handle exception
				}
			}
		}));
		System.setErr(System.out);
		System.out.println("java:已重定向输出到浏览器控制台");
		try {
			JSObject win = JSObject.getWindow(Main.this);
			win.eval("JsNative.onAppletStart()");
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.applet.Applet#stop()
	 */
	@Override
	public void stop() {
		// TODO Auto-generated method stub
		super.stop();
		try {
			JSObject win = JSObject.getWindow(Main.this);
			win.eval("JsNative.onAppletStop()");
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}

}
